﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace TEST8
{
	public partial class Form1 : Form
	{
		int X = 0, Y = 0;//声明定义状态变量

		int Suc = 0, SucS = 0;//统计解总数，优秀解数

		bool FLAG = false;//循环控制

		double time = 0.0;//计时器

		//文件目录及文件名
		string filePath = @"c:\LOG\";

		string fileName1 = @"c:\LOG\Log.txt";

		//设定文件内码 gb2312 简体中文
		Encoding enc = Encoding.GetEncoding("gb2312");

		public Form1()
		{
			InitializeComponent();
		}

		//行动函数——执行灌水等动作
		public int Action(int ActNum)//返回值用于判断此次动作是否有效，参数为执行动作编号
		{
			int RESULT = 0;//用于判断此次动作是否有效，0为无效，有效时返回动作编号

			//r_1:（X，Y|X<4）→（4，Y） 当4升壶不满时，将其灌满
			if (ActNum == 1)
			{
				if (X < 4)
				{
					X = 4;
					RESULT = ActNum;
				}
				else
				{
					RESULT = 0;
				}
			}

			//r_2:（X，Y|Y<3）→（X，3） 当3升壶不满时，将其灌满
			if (ActNum == 2)
			{
				if (Y < 3)
				{
					Y = 3;
					RESULT = ActNum;
				}
				else
				{
					RESULT = 0;
				}
			}

			//r_3:（X，Y|X>0）→（0，Y） 将4升壶中水全部倒掉
			if (ActNum == 3)
			{
				if (X > 0)
				{
					X = 0;
					RESULT = ActNum;
				}
				else
				{
					RESULT = 0;
				}
			}

			//r_4:（X，Y|Y>0）→（X，0） 将3升壶中水全部倒掉
			if (ActNum == 4)
			{
				if (Y > 0)
				{
					Y = 0;
					RESULT = ActNum;
				}
				else
				{
					RESULT = 0;
				}
			}

			//r_5:（X，Y|X+Y≥4∧Y>0）→（4，Y-(4-X)） 将3升壶中水倒向4升壶，直到4升壶水满
			if (ActNum == 5)
			{
				if ((X + Y >= 4) && (Y > 0))
				{
					Y = Y - (4 - X);
					X = 4;

					RESULT = ActNum;
				}
				else
				{
					RESULT = 0;
				}
			}

			//r_6:（X，Y|X+Y≥3∧X>0）→（X-(3-Y)，3）将4升壶中水倒向3升壶，直到3升壶水满
			if (ActNum == 6)
			{
				if ((X + Y >= 3) && (X > 0))
				{
					X = X - (3 - Y);
					Y = 3;

					RESULT = ActNum;
				}
				else
				{
					RESULT = 0;
				}
			}

			//r_7:（X，Y| X+Y≤4∧Y>0）→（X+Y，0） 将3升壶中水全部倒入4升壶
			if (ActNum == 7)
			{
				if ((X + Y <= 4) && (Y > 0))
				{
					X = X + Y;
					Y = 0;

					RESULT = ActNum;
				}
				else
				{
					RESULT = 0;
				}
			}

			//r_8:（X，Y| X+Y≤3∧X>0 ）→（0，X+Y）将4升壶中水全部倒入3升壶
			if (ActNum == 8)
			{
				if ((X + Y <= 3) && (X > 0))
				{
					Y = X + Y;
					X = 0;

					RESULT = ActNum;
				}
				else
				{
					RESULT = 0;
				}
			}

			return RESULT;

		}
		//停止循环按钮
		private void Button2_Click(object sender, EventArgs e)
		{
			timer1.Stop();
			timer1.Enabled = false;
			FLAG = false;
			this.Refresh();//刷新
			Application.DoEvents();//响应用户操作
		}
		//用于文本框的自动滚动
		private void RichTextBox1_TextChanged(object sender, EventArgs e)
		{
			//将光标位置设置到当前内容的末尾
			richTextBox1.SelectionStart = richTextBox1.Text.Length;
			//滚动到光标位置
			richTextBox1.ScrollToCaret();
		}

		private void Timer1_Tick(object sender, EventArgs e)
		{
			time += 0.1;//计时器每一跳是100ms，也就是0.1s
		}

		//开始按钮
		private void Button1_Click(object sender, EventArgs e)
		{
			timer1.Enabled = true;
			timer1.Start();//开始计时

			X = 0;
			Y = 0;//状态变量初始化

			int a = 0, b = 0, olda = 0;//用于决定/判断动作编号

			bool BEST = false;//统计最优解是否被算出

			int EFroop = 0;//有效步数
			int roop = 0;//总循环次数

			bool fail = false;//是否求解失败(路径过长)

			FLAG = true;

			//准备写入文件，检查文件夹是否存在，若不存在则新建
			if (!Directory.Exists(filePath))
				Directory.CreateDirectory(filePath);

			//使用全局位移标识符GUID的哈希值为种子产生随机数（随机性较高）
			var r = new Random(Guid.NewGuid().GetHashCode());


			while (FLAG)//连续求解循环，不按停止键就一直循环
			{
				//变量初始化
				X = 0;
				Y = 0;//重置状态变量

				a = 0;//即将执行的操作编号
				olda = 0;//上次执行过的操作编号

				EFroop = 0;
				roop = 0;

				fail = false;



				GC.Collect();
				string s = "";//用于保存求解路径

				while (X != 2)//目标状态判断
				{
					while (olda == a)//新生成的随机操作编号如果是上次刚刚执行过的就重新生成
					{
						r = new Random(Guid.NewGuid().GetHashCode());
						a = r.Next(1, 8);//生成随机的操作编号
					}

					b = Action(a);//执行操作
					

					if (b == 0)//判断刚刚的操作是否有效
					{
						r = new Random(Guid.NewGuid().GetHashCode());
						a = r.Next(1, 8);//生成随机的操作编号
					}
					else
					{
						s += a.ToString();//有效的话就把这个操作记录在求解路径中
						olda = a;//记下刚刚的操作，用于避免重复操作
						EFroop++;
						if (EFroop >= 1000)
						{
							fail = true;
							break;
						}

					}

					roop++;

					Application.DoEvents();//响应用户操作

				}


				Suc++;//已经求出一个解
				if (EFroop < 20)//看看这个解是否优秀
				{
					if (EFroop == 6 && BEST == false)//是不是6步的最优解
					{
						BEST = true;
						label12.Text = string.Format("{0:f1}", time);
					}

					string dataforfile = s + "\r\n";

					bool flag = true;
					string[] content = File.ReadAllLines(fileName1);
					foreach (string str in content)
					{
						if (s == str)
						{
							flag = false;
						}
					}

					if (flag)
					{
						File.AppendAllText(fileName1, dataforfile, enc);
						SucS++;//优秀的话
						label4.Text = EFroop.ToString();
						label5.Text = SucS.ToString();
						//输出和文件输出
						richTextBox1.Text += s;
						richTextBox1.Text += Environment.NewLine;
					}

				}

				//输出
				if (fail == false)
				{
					label3.Text = EFroop.ToString();
					label1.Text = Suc.ToString();
					label2.Text = string.Format("{0:f1}", time);
					this.Refresh();
				}



			}




		}
	}
}
